package com.xdf.xzymanagementsystem.aop;

import com.xdf.xzymanagementsystem.dto.ColumnConfigDTO;
import com.xdf.xzymanagementsystem.enums.OperateConstant;
import com.xdf.xzymanagementsystem.enums.PermissionConstant;
import com.xdf.xzymanagementsystem.enums.SeparatorConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * @program: xzy-management-system
 * @description: 菜单切面
 * @author: 张柯
 * @create: 2021-08-05 16:15
 **/
@Component
@Slf4j
@Aspect
public class SysUserTableConfigAspect extends AbstractArgsGetter {
    private static final String PRICE = "PRICE";
    private static final String MONEY = "MONEY";
    private static final String COST = "COST";

    @Pointcut("execution(* com.xdf.xzymanagementsystem.controller.SysUserTableConfigController.calculate(..))")
    private void selectCut() {
    }

    @Pointcut("execution(java.util.List<java.util.Map<String,Object>> com.xdf.xzymanagementsystem.controller.*Controller.*(..))")
    private void cutDataSource() {
    }

    /**
     * 拦截权限
     *
     * @param joinPoint
     * @return
     */
    @Around("selectCut()")
    @SuppressWarnings("unchecked")
    public Object aroundCut(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] param = joinPoint.getArgs();
        Object result = joinPoint.proceed(param);
        if (result instanceof Map) {
            Map<String, ColumnConfigDTO> map = (Map<String, ColumnConfigDTO>) result;
            for (String key : map.keySet()) {
                ColumnConfigDTO entity = map.get(key);
                if (!hasPermission(entity.getSysMenuId() + SeparatorConstant.SEPARATOR + PermissionConstant.PRICE.name())) {
                    if (key.toUpperCase().contains(PRICE) || key.toUpperCase().contains(COST)) {
                        //  隐藏单价
                        entity.setHidden(true);
                    }
                }
                if (!hasPermission(entity.getSysMenuId() + SeparatorConstant.SEPARATOR + PermissionConstant.MONEY.name())) {
                    if (key.toUpperCase().contains(MONEY)) {
                        //  隐藏金额
                        entity.setHidden(true);
                    }
                }
            }
        }
        return result;
    }

    /**
     * 根据权限去除或者保留当前接口中的单价与金额
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("cutDataSource()")
    @SuppressWarnings("unchecked")
    public Object aroundDataSourceGet(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();
        String name = joinPoint.getSignature().getName();
        Class<?> clazz = joinPoint.getTarget().getClass();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method targetMethod = clazz.getMethod(name, signature.getParameterTypes());
        Annotation[] annos = targetMethod.getAnnotations();
        for (Annotation annotation : annos) {
            if (annotation.annotationType() == RequiresPermissions.class) {
                RequiresPermissions o = (RequiresPermissions) annotation;
                String[] value = o.value();
                Logical logical = o.logical();
                if (value.length <= 0) break;
                String v = value[0];
                String menuId = v.split(SeparatorConstant.SEPARATOR)[0];
                List<Map<String, Object>> list = (List<Map<String, Object>>) result;
                boolean hasPricePermission = hasPermission(concatPermission(menuId, OperateConstant.PRICE));
                boolean hasMoneyPermission = hasPermission(concatPermission(menuId, OperateConstant.MONEY));
                if (CollectionUtils.isNotEmpty(list)) {
                    if (!hasMoneyPermission || !hasPricePermission) {
                        list.forEach(x -> {
                            if (!hasPricePermission) {
                                setPriceFieldNull(x);
                            }
                            if (!hasMoneyPermission) {
                                setMoneyFieldNull(x);
                            }
                        });
                    }
                }
                break;
            }
        }
        return result;
    }

    private String concatPermission(String menuId, String operate) {
        return menuId + SeparatorConstant.SEPARATOR + operate;
    }

    /**
     * 设置单价为空
     *
     * @param map
     */
    private void setPriceFieldNull(Map<String, Object> map) {
        if (map == null) return;
        for (String key : map.keySet()) {
            if (key.toUpperCase().contains(PRICE) || key.toUpperCase().contains(COST)) {
                map.put(key, 0);
            }
        }
    }

    /**
     * 设置金额为空
     *
     * @param map
     */
    private void setMoneyFieldNull(Map<String, Object> map) {
        if (map == null) return;
        for (String key : map.keySet()) {
            if (key.toUpperCase().contains(MONEY)) {
                map.put(key, 0);
            }
        }
    }
}